package rpg.writer.app.player;

import java.awt.BorderLayout;
import java.util.List;

import javax.swing.JPanel;

import rpg.client.Instruction;
import rpg.client.model.Actor;
import rpg.client.model.ActorInfo;
import rpg.client.model.ClientMap;
import rpg.client.model.Dialog;
import rpg.client.model.GameEvent;
import rpg.client.model.Position;
import rpg.engine.client.GameEngineFacade;

public class PlayerJPanel extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 6190171590411002016L;

    private static void debug(Object o) {
        // System.out.println("PlayerJPanel: " + o);
    }

    private final ClientJPanel client;
    private volatile String playerID = null;
    private volatile GameEngineFacade engine = null;
    private volatile Communication communication = null;

    private final MapJPanel map = new MapJPanel(this);
    private final InstructionJPanel instructions = new InstructionJPanel(this);

    public PlayerJPanel(ClientJPanel clientJPanel) {
        super(new BorderLayout());
        client = clientJPanel;
        add(map, BorderLayout.CENTER);
        add(instructions, BorderLayout.EAST);
    }

    public void character() {
        ActorInfo ai = engine.character(playerID);

        CharacterJPanel cjp = new CharacterJPanel(playerID, ai);
        cjp.setVisible(true);

        for (Instruction i : cjp.getInstructions()) {
            communication.sendInstruction(i);
        }
    }

    public void launch(Actor pc) {
        if (communication != null) {
            communication.requestStop();
        }

        playerID = pc.getId();
        communication = new Communication(pc, engine, this);
        map.setCommunication(communication, pc.getId());
        Thread t = new Thread(communication);
        t.start();
        map.requestFocus();
    }

    private Instruction render(Dialog info) {
        debug(info);

        if (info.getText().length() == 0) {
            return null;
        }

        Actor actor = engine.getActor(info.getActorId());
        DialogJPanel djp = new DialogJPanel(info, actor);
        djp.setVisible(true);

        if ((djp.getStoryID().length() > 0) && (djp.getChatID().length() > 0)) {
            return Instruction.startChat(playerID, djp.getStoryID(), djp.getChatID(), "");
        }

        return null;
    }

    public Instruction render(GameEvent event) {
        debug(event);

        Instruction instruction = null;

        switch (event.getType()) {
            case CHANGE_POSITION:
            case CHANGE_MAP:
                Position playerPosition = event.getPosition();
                ClientMap clientMap = engine.getGameMap(playerPosition.getMapID());
                map.display(clientMap, playerPosition, event.getFacing());
                break;
            case CHAT_INSTRUCTION:
                return Instruction.startChat(playerID, event.getStoryID(), event.getId(), "?");
            case RENDER_CHAT:
                Dialog info = engine.getDialog(event.getStoryID(), event.getId());
                instruction = render(info);
                break;
            default:
                System.out.println("No implemention to render: " + event);
                break;
        }

        return instruction;
    }

    public void repack() {
        client.repack();
    }

    public void sendInstruction(Instruction instruction) {
        if (communication != null) {
            communication.sendInstruction(instruction);
        }
    }

    public void setEngine(GameEngineFacade facade) {
        engine = facade;
    }

    public void updateInstruction(List<Instruction> possibleInstructions) {
        debug("uI: " + possibleInstructions);
        boolean update = instructions.update(possibleInstructions);
        debug("uI: " + update);
        client.repack();
        map.requestFocus();
    }
}
